package io.mycat.config.model.encrypt;

import java.nio.charset.StandardCharsets;

/**
 * 自定义加密类
 * （自己填充 encode 和 decode 方法，实现自己的加密逻辑，其他方法不要动，填充完毕测试无误后 install，将 lib 下的 encrypt-core-2.0.jar 替换即可）
 * @author zrx
 */
public class EncryptHelper {

	/**
	 * 加密前缀 此前缀不要动，不然无法解密
	 */
	public static final String PRE_ENCRYPT = "!zl";

	/**
	 * 加密
	 *
	 * @param data byte[]
	 * @return byte[]
	 */
	public static byte[] encode(byte[] data) {
		//TODO 实现自己的加密逻辑
		return new byte[]{};
	}

	/**
	 * 解密
	 *
	 * @param data byte[]
	 * @return byte[]
	 */
	public static byte[] decode(byte[] data) {
		//TODO 实现自己的解密逻辑
		return new byte[]{};
	}


	public static String hex(byte[] bytes) {
		StringBuilder result = new StringBuilder();
		for (byte aByte : bytes) {
			result.append(String.format("%02x", aByte));
			// upper case
			// result.append(String.format("%02X", aByte));
		}
		return result.toString();
	}

	public static String hexWithPre(byte[] bytes) {
		StringBuilder result = new StringBuilder();
		for (byte aByte : bytes) {
			result.append(String.format("%02x", aByte));
			// upper case
			// result.append(String.format("%02X", aByte));
		}
		return PRE_ENCRYPT + result.toString();
	}

	/**
	 * 字符串转换为16进制字符串
	 *
	 * @param s
	 * @return
	 */
	public static String stringToHexString(String s) {
		StringBuilder str = new StringBuilder();
		for (int i = 0; i < s.length(); i++) {
			int ch = s.charAt(i);
			String s4 = Integer.toHexString(ch);
			str.append(s4);
		}
		return str.toString();
	}

	/**
	 * 16进制字符串转换为字符串
	 *
	 * @param s
	 * @return
	 */
	public static String hexStringToString(String s) {
		if (s == null || "".equals(s)) {
			return null;
		}
		s = s.replace(" ", "");
		byte[] baKeyword = new byte[s.length() / 2];
		for (int i = 0; i < baKeyword.length; i++) {
			try {
				baKeyword[i] = (byte) (0xff & Integer.parseInt(
						s.substring(i * 2, i * 2 + 2), 16));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		try {
			s = new String(baKeyword, StandardCharsets.UTF_8);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return s;
	}

	/**
	 * 字符串转化为字节数组
	 *
	 * @param hexString the hex string
	 * @return byte[]
	 */
	public static byte[] hexStringToBytes(String hexString) {

		if (hexString == null || "".equals(hexString)) {
			return null;
		}
		hexString = hexString.replace(PRE_ENCRYPT, "");
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d;
		//转换的时候应该注意的是单双数的情况，网上很多都只处理了双数的情况，也就是默认刚好填满，这样16进制字符串长度是单数的话会丢失掉一个字符 因为length/2 是舍去余数的
		if (hexString.length() % 2 != 0) {
			// 16进制字符串长度是单数
			length = length + 1;
			d = new byte[length];
			// 这里把byte数组从后往前填，字符串也是翻转着填的，最后会空出byte数组的第一个（用来填充我们单出来的那个字符）
			for (int i = length - 1; i > 0; i--) {
				int pos = i * 2;
				d[i] = (byte) (charToByte(hexChars[pos]) | charToByte(hexChars[pos - 1]) << 4);
			}
			d[0] = charToByte(hexChars[0]);
		} else {// 双数情况
			d = new byte[length];
			for (int i = 0; i < length; i++) {
				int pos = i * 2;
				d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
			}
		}
		return d;
	}

	/**
	 * Convert char to byte
	 *
	 * @param c char
	 * @return byte
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	public static void main(String[] args) {
		String str = "测试加密";
		String encode = hex(encode(str.getBytes(StandardCharsets.UTF_8)));
		System.out.println("加密后的16进制：" + encode);
		System.out.println("加密后的16进制长度：" + encode.length());
		/*String decode = hex(decode(hexStringToBytes(encode)));
		System.out.println("解密后的16进制：" + decode);*/
		System.out.println("解密后的字符串：" + new String(decode(hexStringToBytes(encode)), StandardCharsets.UTF_8));
	}
}
